using System;
using System.Linq;
using Domain.Dto;
using Domain.Interface;
using Domain.Model;
using Gmmy.DomainExtension;
using Gmmy.Utility;
using Surging.Core.CPlatform.Ioc;
using System.Threading.Tasks;
using Gmmy.Utility.Extensions;

namespace Domain.Services
{
    public class ModuleDomainService : ServiceBase,IModuleDomainService
    {
        private readonly IModuleRepository _repository;
        private readonly IModuleActionRepository _actionRepository;

        public ModuleDomainService(IModuleRepository repository, IModuleActionRepository actionRepository)
        {
            this._repository = repository;
            _actionRepository = actionRepository;
        }

		/// <summary>
        /// 创建功能模块
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Create(ModuleCreateInput input)
        {
            if (input.FId != Guid.Empty)
            {
                var father = await _repository.GetByKeyAsync(input.FId);
                if (father == null || father.IsDeleted)
                {
                    throw new CustomException("所选父模块不存在!");
                }
                if (!father.IsDeleted)
                {
                    if (await _actionRepository.ExistsAsync(
                        new DirectSpecification<ModuleAction>(x => x.ModuleId == input.FId && !x.IsDeleted)))
                    {
                        throw new CustomException("所选父模块已有功能,无法创建子模块!");
                    }
                }
            }
            var module = new Module(input);
            _repository.Add(module);
            if (input.ActionList.Any())
            {
                if (input.ActionList.GroupBy(x => (x.Sort ?? 0)).Any(x => x.Count() > 1))
                {
                    throw new CustomException("功能序号必须唯一!");
                }
                input.ActionList.ForEach(x =>
                {
                    x.ModuleId = module.ID;
                    var action = new ModuleAction(x);
                    _actionRepository.Add(action);
                });
            }
        }

        /// <summary>
        /// 更新功能模块
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Update(ModuleUpdateInput input)
        {
            var model = await _repository.GetByKeyAsync(input.ID);
            if (model == null)
            {
                throw new CustomException("所选功能模块不存在!");
            }
            if (input.FId != Guid.Empty)
            {
                var father = await _repository.GetByKeyAsync(input.FId);
                if (father == null || father.IsDeleted)
                {
                    throw new CustomException("所选父模块不存在!");
                }
                if (!father.IsDeleted)
                {
                    if (await _actionRepository.ExistsAsync(
                        new DirectSpecification<ModuleAction>(x => x.ModuleId == input.FId && !x.IsDeleted)))
                    {
                        throw new CustomException("所选父模块已有功能,无法创建子模块!");
                    }
                }
            }
            if (await _repository.ExistsAsync(new DirectSpecification<Module>(x => x.FId == input.ID)) &&
                input.ActionList.Any())
            {
                throw new CustomException("当前模块已有子模块,无法新增功能!");
            }
            model.Update(input);
            _repository.Update(model);
            //
            //处理action
            var oldAction =
            (await _actionRepository.GetManyAsync(
                new DirectSpecification<ModuleAction>(x => x.ModuleId == input.ID))).ToList();
            _actionRepository.LogicDelete(new DirectSpecification<ModuleAction>(x => oldAction.Select(y => y.ID).Except(input.ActionList.Select(y => y.ID ?? Guid.Empty)).Contains(x.ID)));
            oldAction.Select(y => y.ID).Intersect(input.ActionList.Select(y => y.ID ?? Guid.Empty)).ToList().ForEach(x =>
            {
                input.ActionList.FirstOrDefault(y => y.ID == x);
                var targetAction= oldAction.FirstOrDefault(y => y.ID.Equals(x));
                targetAction.Update(input.ActionList.FirstOrDefault(y => y.ID.Equals(x)));
                _actionRepository.Modify(targetAction);
            });
            input.ActionList.Where(x=>x.ID==null).ToList().ForEach(x =>
            {
                x.ModuleId = model.ID;
                var action = new ModuleAction(x.MapTo<ModuleActionCreateInput,ModuleActionUpdateInput>());
                _actionRepository.Add(action);
            });
        }
    }
}
